﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SZORM.Mapper;

namespace SZORM.Core.Infrastructure.Interception
{
    internal class QueryAsyncEnumeratorCreator
    {
        public static IAsyncEnumerator<T> CreateAsyncEnumerator<T>(InternalAdoSession adoSession, DbCommandFactor commandFactor)
        {
            return new QueryAsyncEnumerator<T>(adoSession, commandFactor);
        }
    }
    sealed class QueryAsyncEnumerator<T> : IAsyncEnumerator<T>
    {
        private readonly InternalAdoSession _adoSession;
        private readonly DbCommandFactor _commandFactor;
        private readonly IObjectActivator _objectActivator;

        private IDataReader _reader;
        private T _current;
        private bool _hasFinished;
        private bool _disposed;

        public QueryAsyncEnumerator(InternalAdoSession adoSession, DbCommandFactor commandFactor)
        {
            _adoSession = adoSession;
            _commandFactor = commandFactor;
            _objectActivator = commandFactor.ObjectActivator;
        }

        public T Current => _current;

        public async ValueTask<bool> MoveNextAsync()
        {
            if (_hasFinished || _disposed)
                return false;

            if (_reader == null)
            {
                // 异步执行命令
                _reader = await _adoSession.ExecuteReaderAsync(_commandFactor.CommandText, _commandFactor.Parameters, CommandType.Text).ConfigureAwait(false);
            }

            if (_reader.Read())
            {
                _current = (T)_objectActivator.CreateInstance(_reader);
                return true;
            }
            else
            {
                _reader.Close();
                _current = default;
                _hasFinished = true;
                return false;
            }
        }

        public ValueTask DisposeAsync()
        {
            if (_disposed)
                return new ValueTask();

            if (_reader != null)
            {
                if (!_reader.IsClosed)
                    _reader.Close();
                _reader.Dispose();
                _reader = null;
            }

            _current = default;
            _disposed = true;
            return new ValueTask();
        }
    }
}
